home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / Other Langs / PowerLisp 1.01 / Library / assembler.lisp < prev    next >
Encoding:
Text File  |  1993-08-27  |  24.6 KB  |  846 lines  |  [TEXT/ROSA]

  1. ;
  2. ;        Copyright © 1993 Roger Corman. All rights reserved.
  3. ;
  4.  
  5. ;
  6. ;    Source code for assembler.
  7. ;
  8.  
  9. (provide :assembler)
  10. (in-package :assembler)
  11.  
  12. (export 
  13. '(
  14.      a0  a1  a2  a3  a4  a5  a6  a7
  15.     -a0 -a1 -a2 -a3 -a4 -a5 -a6 -a7
  16.      a0+ a1+ a2+ a3+ a4+ a5+ a6+ a7+
  17.      d0  d1  d2  d3  d4  d5  d6  d7
  18.     d-registers
  19.     a-registers
  20.     a-inc-registers
  21.     a-dec-registers
  22.     $CAR
  23.     $CDR
  24.     $SETCAR
  25.     $SETCDR
  26.     $SYMBOL-VALUE
  27.     $SYMBOL-PLIST
  28.     $NODE-TYPE
  29.     $CONSP
  30.     $INTEGER
  31.     $RETURN
  32.     $FUNC-BEGIN
  33.     $IF
  34.     $IFELSE
  35.     $REFERENCE
  36.     link
  37.     unlk
  38.     rts
  39.     dc.w
  40.     dc.l
  41.     moveq
  42.     move.l
  43.     move.b
  44.     move.w
  45.     movea.l
  46.     add.l
  47.     addi.l
  48.     and.l
  49.     andi.l
  50.     or.l
  51.     ori.l
  52.     eor.l
  53.     eori.l
  54.     sub.l
  55.     cmp.l
  56.     tst.l
  57.     subi.l
  58.     clr.l
  59.     lea
  60.     jsr
  61.     bra
  62.     bsr
  63.     bhi
  64.     bls
  65.     bcc
  66.     bcs
  67.     bne
  68.     beq
  69.     bvc
  70.     bvs
  71.     bpl
  72.     bmi
  73.     bge
  74.     blt
  75.     bgt
  76.     ble
  77.     movem.l
  78. ))
  79.  
  80. (defconstant a0 0)
  81. (defconstant a1 1)
  82. (defconstant a2 2)
  83. (defconstant a3 3)
  84. (defconstant a4 4)
  85. (defconstant a5 5)
  86. (defconstant a6 6)
  87. (defconstant a7 7)
  88.  
  89. (defconstant a0+ 0)
  90. (defconstant a1+ 1)
  91. (defconstant a2+ 2)
  92. (defconstant a3+ 3)
  93. (defconstant a4+ 4)
  94. (defconstant a5+ 5)
  95. (defconstant a6+ 6)
  96. (defconstant a7+ 7)
  97.  
  98. (defconstant -a0 0)
  99. (defconstant -a1 1)
  100. (defconstant -a2 2)
  101. (defconstant -a3 3)
  102. (defconstant -a4 4)
  103. (defconstant -a5 5)
  104. (defconstant -a6 6)
  105. (defconstant -a7 7)
  106.  
  107. (defconstant d0 0)
  108. (defconstant d1 1)
  109. (defconstant d2 2)
  110. (defconstant d3 3)
  111. (defconstant d4 4)
  112. (defconstant d5 5)
  113. (defconstant d6 6)
  114. (defconstant d7 7)
  115.  
  116. (defconstant d-registers '(d0 d1 d2 d3 d4 d5 d6 d7))
  117. (defconstant a-registers '(a0 a1 a2 a3 a4 a5 a6 a7))
  118. (defconstant a-inc-registers '(a0+ a1+ a2+ a3+ a4+ a5+ a6+ a7+))
  119. (defconstant a-dec-registers '(-a0 -a1 -a2 -a3 -a4 -a5 -a6 -a7))
  120.  
  121. ;;    Macros to access SYMBOL and NODE fields.
  122. ;;    These are dependent on the symbol class definition.
  123. ;;    The C++ source is in LispObjects.h.
  124.  
  125. (defconstant *symbol-value-offset*                 8)
  126. (defconstant *symbol-plist-offset*                 12)
  127. (defconstant *symbol-package-offset*             16)
  128. (defconstant *symbol-name-offset*                 20)
  129. (defconstant *symbol-flags-offset*                 24)
  130. (defconstant *symbol-jump-table-entry-offset*     26)
  131. (defconstant *symbol-jump-address-offset*         28)
  132. (defconstant *symbol-function-offset*             32)
  133.  
  134. (defconstant *node-car-offset*                    0)
  135. (defconstant *node-cdr-offset*                    4)
  136. (defconstant *node-flags-offset*                8)
  137. (defconstant *node-type-offset*                    9)
  138.  
  139. (defconstant *node-integer-offset*                0)    ;; occupies the car field
  140.  
  141. (defvar *assembler-address*    0)
  142. (defvar *assembler-local-address*    0)    ;; keep track of offset within instruction
  143. (defvar *assembler-references*    nil)
  144.  
  145. (defmacro $CAR (areg &optional dest-reg)
  146.     (unless dest-reg (setq dest-reg areg))
  147.     `(
  148.         (move.l (,areg ,*node-car-offset*) ,dest-reg)
  149.      )) 
  150.  
  151. (defmacro $CDR (areg &optional dest-reg)
  152.     (unless dest-reg (setq dest-reg areg))
  153.     `(
  154.         (move.l (,areg ,*node-cdr-offset*) ,dest-reg)
  155.      )) 
  156.  
  157. (defmacro $SETCAR (areg value)
  158.     `(
  159.         (move.l ,value (,areg ,*node-car-offset*))
  160.      )) 
  161.  
  162. (defmacro $SETCDR (areg value)
  163.     `(
  164.         (move.l ,value (,areg ,*node-cdr-offset*))
  165.      )) 
  166.  
  167. (defmacro $SYMBOL-VALUE (areg)
  168.     `(
  169.         (move.l (,areg) ,areg)
  170.         (move.l (,areg ,*symbol-value-offset*) ,areg)
  171.         (move.l (,areg) ,areg)
  172.      )) 
  173.  
  174. (defmacro $SYMBOL-PLIST (areg)
  175.     `(
  176.         (move.l (,areg) ,areg)
  177.         (move.l (,areg ,*symbol-plist-offset*) ,areg)
  178.      )) 
  179.  
  180. ;; Extract the type field from a node
  181. (defmacro $NODE-TYPE (areg dest)
  182.     `(
  183.         (move.l (,areg ,(- *node-type-offset* 3)) ,dest)
  184.         (andi.l #x000000ff ,dest)
  185.     ))
  186.     
  187. (defmacro $CONSP (areg)
  188.     `(
  189.         ($NODE-TYPE ,areg d0)
  190.         (cmp.l 0 d0)
  191.     ))
  192.  
  193. (defmacro $INTEGER (areg &optional dest-reg)
  194.     (unless dest-reg (setq dest-reg areg))
  195.     `(
  196.         (move.l (,areg ,*node-integer-offset*) ,dest-reg)
  197.      )) 
  198.  
  199.     
  200. ;;
  201. ;;    The $RETURN macro zeros out the multiple value cell, stores
  202. ;;    the passed value in d0 (to return it), and unlinks the stack frame.
  203. ;;
  204. (defmacro $RETURN (retval)
  205.     (if (eq retval 'd0)
  206.         `(
  207.             (clr.l (common-lisp::%multiple-values-address))
  208.             (unlk a6)
  209.             (rts)
  210.          ) 
  211.         `(
  212.             (clr.l (common-lisp::%multiple-values-address))
  213.             (move.l ,retval d0)
  214.             (unlk a6)
  215.             (rts)
  216.          ))) 
  217.  
  218. ;;
  219. ;;    The $FUNC-BEGIN macro sets up the A6 stack frame link,
  220. ;;    and stores a pointer to the parameter block in A0.
  221. ;;    Usage:
  222. ;;        ($FUNC-BEGIN 4)        ;; allocates 4 bytes (space for one object)
  223. ;;                            ;; on the stack
  224. ;;
  225. (defmacro $FUNC-BEGIN (size)
  226.     `(
  227.         (link a6 ,size)
  228.         (move.l (a6 8) a0)
  229.      )) 
  230.  
  231. ;;
  232. ;;    $IF macro
  233. ;;    Usage:
  234. ;;        ($IF    
  235. ;;            (cmp.l d3 0)         ;; if d3 == 0 the next statement will be executed
  236. ;;            (
  237. ;;                (move.l d0 d3)
  238. ;;            ))
  239. ;;
  240. (defmacro $IF (condition instructions)
  241.     (let ((temp-label (gensym)))
  242.         ;;    allow single instruction clauses or lists of instructions
  243.         (if (not (listp (car condition)))
  244.             (setq condition (list condition)))
  245.         (if (not (listp (car instructions)))
  246.             (setq instructions (list instructions)))
  247.  
  248.         `(
  249.             ,@condition
  250.             (bne ,temp-label)
  251.             ,@instructions
  252.             ,temp-label
  253.          ))) 
  254.  
  255. ;;
  256. ;;    $IFELSE macro
  257. ;;    Usage:
  258. ;;        ($IFELSE    
  259. ;;            (cmp.l d3 0)         ;; if d3 == 0 the next instruction will be executed
  260. ;;            (
  261. ;;                (move.l d0 d3)
  262. ;;            )
  263. ;;            (
  264. ;;                (move.l d2 d3)    ;; otherwise this instruction will be executed
  265. ;;            ))
  266. ;;
  267. (defmacro $IFELSE (condition if-instructions else-instructions)
  268.     (let ((else-label (gensym)) 
  269.           (exit-label (gensym)))
  270.  
  271.         ;;    allow single instruction clauses or lists of instructions
  272.         (if (not (listp (car condition)))
  273.             (setq condition (list condition)))
  274.         (if (not (listp (car if-instructions)))
  275.             (setq if-instructions (list if-instructions)))
  276.         (if (not (listp (car else-instructions)))
  277.             (setq else-instructions (list else-instructions)))
  278.         
  279.         `(
  280.             ,@condition
  281.             (bne ,else-label)
  282.             ,@if-instructions
  283.             (bra ,exit-label)
  284.             ,else-label
  285.             ,@else-instructions
  286.             ,exit-label
  287.          ))) 
  288.  
  289. ;;
  290. ;;    The $REFERENCE macro does not generate any instructions, but
  291. ;;    is used by the compiler as a flag to the assembler to correctly
  292. ;;    generate address reference entries when code is compiled to a file.
  293. ;;
  294. (defmacro $REFERENCE (referenced-item)
  295.     nil)
  296.     
  297. (defmacro link (areg offset) `(,(+ (symbol-value areg) #x4e50) ,offset))
  298. (defmacro unlk (areg) `(,(+ (symbol-value areg) #x4e58)))
  299. (defmacro rts () `(#x4e75))
  300. (defmacro dc.w (w) 
  301.     (cond 
  302.         ((symbolp w) 
  303.          (add-reference `(%symbol-value-word ,w) -2)
  304.          (list (symbol-value w)))
  305.         (t (list w))))
  306.  
  307. (defmacro dc.l (w) 
  308.     (cond 
  309.         ((symbolp w) 
  310.          (add-reference `(%symbol-value ,w) -2)
  311.          (multiple-value-list (truncate (symbol-value w) #x10000)))
  312.         (t (multiple-value-list (truncate w #x10000)))))
  313.         
  314. (defmacro moveq (byte dreg)
  315.     (if (or (< byte 0) (> byte 255)) 
  316.         (error "Data out of range.~%Instruction: moveq  Value: ~A" byte))
  317.     (unless (member dreg d-registers) 
  318.         (error "Invalid data register. ~%Instruction: moveq  Operand: ~A" dreg))
  319.     (list (+ #x7000 byte (* (symbol-value dreg) #x200))))
  320.  
  321. (defmacro move.l (sreg dreg)
  322.     (move-instruction sreg dreg 'long))
  323.  
  324. (defmacro move.b (sreg dreg)
  325.     (move-instruction sreg dreg 'byte))
  326.  
  327. (defmacro move.w (sreg dreg)
  328.     (move-instruction sreg dreg 'word))
  329.  
  330. (defun move-instruction (sreg dreg size)
  331.     (let ((s (encode-address sreg size))(d (encode-address dreg size)) op-code)
  332.         (setq op-code 
  333.             (case size
  334.                 (long #x2000)
  335.                 (byte #x1000)
  336.                 (word #x3000)))
  337.         `(,(+ op-code 
  338.                 (* (encoded-address-reg d) #x200) ; destination register bits 9-11
  339.                 (* (encoded-address-mode d) #x40) ; destination mode bits 6-8
  340.                 (* (encoded-address-mode s) #x8)  ; source mode bits 3-5
  341.                 (encoded-address-reg s))          ; source register
  342.             ,@(encoded-address-data s)
  343.             ,@(encoded-address-data d))))
  344.         
  345.             
  346. (defmacro movea.l (sreg dreg)
  347.     (unless (member dreg a-registers) 
  348.         (error "Invalid address register. ~%Instruction: movea.l  Operand: ~A" dreg))
  349.     (let ((s (encode-address sreg))(d (symbol-value dreg)))
  350.         (append
  351.             (list (+ #x2040 
  352.                     (* d #x200)                ; destination register bits 9-11
  353.                     (* (encoded-address-mode s) #x8) ; source mode bits 3-5
  354.                     (encoded-address-reg s)))         ; source register
  355.             (encoded-address-data s))))
  356.  
  357. (defmacro add.l (src dest)
  358.     (let ((s (encode-address src))(d (encode-address dest)))
  359.         (unless (or (= (encoded-address-mode s) 0) 
  360.                     (= (encoded-address-mode d) 0))
  361.             (error 
  362.                 "The source or destination must be a d-register. ~%Instruction: add.l  Operands: ~A, ~A" src dest))
  363.         (if (= (encoded-address-mode s) 0)    ; if D-register is source
  364.             `(,(+ #xD000 
  365.                 (* (encoded-address-reg s) #x200)        ; source register bits 9-11
  366.                 (* 6 #x40)                                ; op-mode bits 6-8
  367.                 (* (encoded-address-mode d) #x8)        ; dest mode bits 3-5
  368.                 (encoded-address-reg d))                ; dest register
  369.                 ,@(encoded-address-data d))
  370.                                         ; else D-register is destination
  371.             `(,(+ #xD000 
  372.                 (* (encoded-address-reg d) #x200)        ; dest register bits 9-11
  373.                 (* 2 #x40)                                ; op-mode bits 6-8
  374.                 (* (encoded-address-mode s) #x8)        ; src mode bits 3-5
  375.                 (encoded-address-reg s))                ; src register
  376.                 ,@(encoded-address-data s)))))
  377.  
  378. (defmacro addi.l (src dest)
  379.     (incf *assembler-local-address* 4)
  380.     (let ((s src)(d (encode-address dest)))
  381.         (unless (integerp s)
  382.             (error "The source must be an integer. ~%Instruction: addi.l  Operand: ~A" s))
  383.         `(,(+ #x0680 
  384.                 (* (encoded-address-mode d) #x8)    ; dest mode bits 3-5
  385.                 (encoded-address-reg d))            ; dest register
  386.                 ,@(multiple-value-list (truncate s #x10000))
  387.                 ,@(encoded-address-data d))))
  388.  
  389. (defmacro and.l (src dest)
  390.     (let ((s (encode-address src))(d (encode-address dest)))
  391.         (unless (or (= (encoded-address-mode s) 0) 
  392.                     (= (encoded-address-mode d) 0))
  393.             (error 
  394.                 "The source or destination must be a d-register. ~%Instruction: and.l  Operands: ~A, ~A" src dest))
  395.         (if (or (= (encoded-address-mode s) 1) 
  396.                 (= (encoded-address-mode d) 1))
  397.             (error 
  398.                 "A-register not allowed as operand. ~%Instruction: and.l  Operands: ~A, ~A" src dest))
  399.         (if (= (encoded-address-mode s) 0); if D-register is source
  400.             `(,(+ #xC000 
  401.                 (* (encoded-address-reg s) #x200) ; source register bits 9-11
  402.                 (* 6 #x40)                        ; op-mode bits 6-8
  403.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  404.                 (encoded-address-reg d))        ; dest register
  405.                 ,@(encoded-address-data d))
  406.                                         ; else D-register is destination
  407.             `(,(+ #xC000 
  408.                 (* (encoded-address-reg d) #x200); dest register bits 9-11
  409.                 (* 2 #x40)                        ; op-mode bits 6-8
  410.                 (* (encoded-address-mode s) #x8); src mode bits 3-5
  411.                 (encoded-address-reg s))        ; src register
  412.                 ,@(encoded-address-data s)))))
  413.  
  414. (defmacro andi.l (src dest)
  415.     (incf *assembler-local-address* 4)
  416.     (let ((s src)(d (encode-address dest)))
  417.         (unless (integerp s)
  418.             (error "The source must be an integer. ~%Instruction: andi.l  Operand: ~A" src))
  419.         (if (= (encoded-address-mode d) 1)
  420.             (error "A-register not allowed as destination. ~%Instruction: andi.l  Operand: ~A" dest))
  421.         `(,(+ #x0280 
  422.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  423.                 (encoded-address-reg d))        ; dest register
  424.                 ,@(multiple-value-list (truncate s #x10000))
  425.                 ,@(encoded-address-data d))))
  426.  
  427. (defmacro or.l (src dest)
  428.     (let ((s (encode-address src))(d (encode-address dest)))
  429.         (unless (or (= (encoded-address-mode s) 0) 
  430.                     (= (encoded-address-mode d) 0))
  431.             (error 
  432.                 "The source or destination must be a d-register. ~%Instruction: or.l  Operands: ~A, ~A" src dest))
  433.         (if (or (= (encoded-address-mode s) 1) 
  434.                 (= (encoded-address-mode d) 1))
  435.             (error 
  436.                 "A-register not allowed as operand. ~%Instruction: or.l  Operands: ~A, ~A" src dest))
  437.         (if (= (encoded-address-mode s) 0)        ; if D-register is source
  438.             `(,(+ #x8000 
  439.                 (* (encoded-address-reg s) #x200); source register bits 9-11
  440.                 (* 6 #x40)                        ; op-mode bits 6-8
  441.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  442.                 (encoded-address-reg d))        ; dest register
  443.                 ,@(encoded-address-data d))
  444.                                         ; else D-register is destination
  445.             `(,(+ #x8000 
  446.                 (* (encoded-address-reg d) #x200); dest register bits 9-11
  447.                 (* 2 #x40)                        ; op-mode bits 6-8
  448.                 (* (encoded-address-mode s) #x8); src mode bits 3-5
  449.                 (encoded-address-reg s))        ; src register
  450.                 ,@(encoded-address-data s)))))
  451.  
  452. (defmacro ori.l (src dest)
  453.     (incf *assembler-local-address* 4)
  454.     (let ((s src)(d (encode-address dest)))
  455.         (unless (integerp s)
  456.             (error "The source of 'ori' must be an integer"))
  457.         (if (= (encoded-address-mode d) 1)
  458.             (error "ori: destination cannot be an a-register"))
  459.         `(,(+ #x0080 
  460.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  461.                 (encoded-address-reg d))        ; dest register
  462.                 ,@(multiple-value-list (truncate s #x10000))
  463.                 ,@(encoded-address-data d))))
  464.  
  465. (defmacro eor.l (src dest)
  466.     (let ((s (encode-address src))(d (encode-address dest)))
  467.         (unless (= (encoded-address-mode s) 0)
  468.             (error "eor: source must be a d-register"))
  469.         (if (= (encoded-address-mode d) 1)
  470.             (error "eor: destination cannot be an a-register"))
  471.         `(,(+ #xB000 
  472.             (* (encoded-address-reg s) #x200); source register bits 9-11
  473.             (* 6 #x40)                        ; op-mode bits 6-8
  474.             (* (encoded-address-mode d) #x8); dest mode bits 3-5
  475.             (encoded-address-reg d))        ; dest register
  476.             ,@(encoded-address-data d))))
  477.  
  478. (defmacro eori.l (src dest)
  479.     (incf *assembler-local-address* 4)
  480.     (let ((s src)(d (encode-address dest)))
  481.         (unless (integerp s)
  482.             (error "The source of 'eori' must be an integer"))
  483.         (if (= (encoded-address-mode d) 1)
  484.             (error "eor.i: destination cannot be an a-register"))
  485.         `(,(+ #x0A80 
  486.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  487.                 (encoded-address-reg d))        ; dest register
  488.                 ,@(multiple-value-list (truncate s #x10000))
  489.                 ,@(encoded-address-data d))))
  490.  
  491. (defmacro sub.l (src dest)
  492.     (let ((s (encode-address src))(d (encode-address dest)))
  493.         (unless (or (= (encoded-address-mode s) 0) 
  494.                     (= (encoded-address-mode d) 0))
  495.             (error "The source or destination of 'sub' must be a d-register"))
  496.         (if (= (encoded-address-mode s) 0)        ; if D-register is source
  497.             `(,(+ #x9000 
  498.                 (* (encoded-address-reg s) #x200); source register bits 9-11
  499.                 (* 6 #x40)                        ; op-mode bits 6-8
  500.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  501.                 (encoded-address-reg d))        ; dest register
  502.                 ,@(encoded-address-data d))
  503.                                         ; else D-register is destination
  504.             `(,(+ #x9000 
  505.                 (* (encoded-address-reg d) #x200); dest register bits 9-11
  506.                 (* 2 #x40)                        ; op-mode bits 6-8
  507.                 (* (encoded-address-mode s) #x8); src mode bits 3-5
  508.                 (encoded-address-reg s))        ; src register
  509.                 ,@(encoded-address-data s)))))
  510.  
  511. (defmacro cmp.l (src dest)
  512.     (let ((s (encode-address src))(d (encode-address dest)))
  513.         (unless (= (encoded-address-mode d) 0)
  514.             (error "The destination of 'cmp' must be a d-register"))
  515.         `(,(+ #xb000 
  516.             (* (encoded-address-reg d) #x200); dest register bits 9-11
  517.             (* 2 #x40)                        ; op-mode bits 6-8
  518.             (* (encoded-address-mode s) #x8); src mode bits 3-5
  519.             (encoded-address-reg s))        ; src register
  520.             ,@(encoded-address-data s))))
  521.  
  522. (defmacro tst.l (dest)
  523.     (let ((d (encode-address dest)))
  524.         `(,(+ #x4A00
  525.                 (* #x40 2)                        ; size = long
  526.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  527.                 (encoded-address-reg d))        ; dest register
  528.                 ,@(encoded-address-data d))))
  529.  
  530. (defmacro subi.l (src dest)
  531.     (incf *assembler-local-address* 4)
  532.     (let ((s src)(d (encode-address dest)))
  533.         (unless (integerp s)
  534.             (error "The source of 'subi' must be an integer"))
  535.         `(,(+ #x0480 
  536.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  537.                 (encoded-address-reg d))        ; dest register
  538.                 ,@(multiple-value-list (truncate s #x10000))
  539.                 ,@(encoded-address-data d))))
  540.  
  541. (defmacro clr.l (dest)
  542.     (let ((d (encode-address dest)))
  543.         `(,(+ #x4200
  544.                 (* #x40 2)                        ; size = long
  545.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  546.                 (encoded-address-reg d))        ; dest register
  547.                 ,@(encoded-address-data d))))
  548.  
  549. (defmacro lea (src dest)
  550.     (let ((s (encode-address src))(d (encode-address dest)))
  551.         (unless (= (encoded-address-mode d) 1)
  552.             (error "The destination of 'lea' must be an a-register"))
  553.         `(,(+ #x41C0
  554.                 (* #x200 (encoded-address-reg d)); dest register bits 9-11
  555.                 (* (encoded-address-mode s) #x8); src mode bits 3-5
  556.                 (encoded-address-reg s))        ; src register
  557.                 ,@(encoded-address-data s))))
  558.  
  559. (defmacro jsr (dst)
  560.  
  561.     (if (symbolp dst) 
  562.         (progn
  563.             (add-reference `(symbol-value ,dst))
  564.             (setq dst (symbol-value dst))))
  565.             
  566.     (if (consp dst)
  567.         (if (eq (car dst) 'function)
  568.             (progn
  569.                 (add-reference dst)
  570.                 (return (cons #x4eb9 
  571.                     (multiple-value-list 
  572.                         (truncate (exec-address (cadr dst)) #x10000))))))
  573.         ;; else
  574.         (error "Invalid destination.~%Instruction: jsr  Destination: ~A" dst))
  575.         
  576.     (let ((d (encode-address dst)))
  577.         (append
  578.             (list (+ #x4e80
  579.                     (* (encoded-address-mode d) #x8); dest mode bits 3-5
  580.                     (encoded-address-reg d)))        ; dest register
  581.             (encoded-address-data d))))
  582.  
  583. (defmacro bra (dest) `(#x6000 ,dest))
  584. (defmacro bsr (dest) `(#x6100 ,dest))
  585. (defmacro bhi (dest) `(#x6200 ,dest))
  586. (defmacro bls (dest) `(#x6300 ,dest))
  587. (defmacro bcc (dest) `(#x6400 ,dest))
  588. (defmacro bcs (dest) `(#x6500 ,dest))
  589. (defmacro bne (dest) `(#x6600 ,dest))
  590. (defmacro beq (dest) `(#x6700 ,dest))
  591. (defmacro bvc (dest) `(#x6800 ,dest))
  592. (defmacro bvs (dest) `(#x6900 ,dest))
  593. (defmacro bpl (dest) `(#x6a00 ,dest))
  594. (defmacro bmi (dest) `(#x6b00 ,dest))
  595. (defmacro bge (dest) `(#x6c00 ,dest))
  596. (defmacro blt (dest) `(#x6d00 ,dest))
  597. (defmacro bgt (dest) `(#x6e00 ,dest))
  598. (defmacro ble (dest) `(#x6f00 ,dest))
  599.     
  600. (setf (get 'd0 'post-increment-mask) #x0001)
  601. (setf (get 'd1 'post-increment-mask) #x0002)
  602. (setf (get 'd2 'post-increment-mask) #x0004)
  603. (setf (get 'd3 'post-increment-mask) #x0008)
  604. (setf (get 'd4 'post-increment-mask) #x0010)
  605. (setf (get 'd5 'post-increment-mask) #x0020)
  606. (setf (get 'd6 'post-increment-mask) #x0040)
  607. (setf (get 'd7 'post-increment-mask) #x0080)
  608. (setf (get 'a0 'post-increment-mask) #x0100)
  609. (setf (get 'a1 'post-increment-mask) #x0200)
  610. (setf (get 'a2 'post-increment-mask) #x0400)
  611. (setf (get 'a3 'post-increment-mask) #x0800)
  612. (setf (get 'a4 'post-increment-mask) #x1000)
  613. (setf (get 'a5 'post-increment-mask) #x2000)
  614. (setf (get 'a6 'post-increment-mask) #x4000)
  615. (setf (get 'a7 'post-increment-mask) #x8000)
  616.  
  617. (setf (get 'a7 'pre-decrement-mask) #x0001)
  618. (setf (get 'a6 'pre-decrement-mask) #x0002)
  619. (setf (get 'a5 'pre-decrement-mask) #x0004)
  620. (setf (get 'a4 'pre-decrement-mask) #x0008)
  621. (setf (get 'a3 'pre-decrement-mask) #x0010)
  622. (setf (get 'a2 'pre-decrement-mask) #x0020)
  623. (setf (get 'a1 'pre-decrement-mask) #x0040)
  624. (setf (get 'a0 'pre-decrement-mask) #x0080)
  625. (setf (get 'd7 'pre-decrement-mask) #x0100)
  626. (setf (get 'd6 'pre-decrement-mask) #x0200)
  627. (setf (get 'd5 'pre-decrement-mask) #x0400)
  628. (setf (get 'd4 'pre-decrement-mask) #x0800)
  629. (setf (get 'd3 'pre-decrement-mask) #x1000)
  630. (setf (get 'd2 'pre-decrement-mask) #x2000)
  631. (setf (get 'd1 'pre-decrement-mask) #x4000)
  632. (setf (get 'd0 'pre-decrement-mask) #x8000)
  633.  
  634. (defmacro movem.l (&rest r)
  635.     (incf *assembler-local-address* 2)
  636.     (let ((instruction 0) (mask 0) (ea))
  637.     (if (consp (car r))        ;; post-increment-mode
  638.         (progn
  639.             (setq ea (encode-address (car r)))
  640.             (setq r (cdr r))
  641.             (setq instruction 
  642.                 (+ #x4cc0 
  643.                     (* (encoded-address-mode ea) 8) 
  644.                     (encoded-address-reg ea)))
  645.             (dolist (i r) (setq mask (+ mask (get i 'post-increment-mask))))
  646.             (return (list* instruction mask (encoded-address-data ea)))) 
  647.         (progn                ;; else pre-decrement-mode
  648.             (setq ea (encode-address (car (last r))))
  649.             (setq instruction 
  650.                 (+ #x48c0 
  651.                     (* (encoded-address-mode ea) 8) 
  652.                     (encoded-address-reg ea)))
  653.             (dolist (i r) 
  654.                 (if (symbolp i)
  655.                     (setq mask (+ mask (get i 'pre-decrement-mask)))))
  656.             (return (list* instruction mask (encoded-address-data ea))))))) 
  657.  
  658. (defun long-words (addr) (multiple-value-list (truncate addr #x10000)))
  659.  
  660. ;
  661. ;    encode-address
  662. ;    Returns a list consisting of:
  663. ;        (mode reg data1 data2 data3 ...)
  664. ;    where there may be [0..n] data words (16-bit quantities)
  665. ;
  666. (defun encode-address (addr &optional (size 'long) &aux retval) 
  667.     (cond
  668.         ((and (consp addr) (eq (car addr) 'function))
  669.          (let ((exec (exec-address (cadr addr))))
  670.             (add-reference addr)
  671.             (setq retval (list* 7 4 (long-words exec)))))
  672.  
  673.         ((and (consp addr) (eq (car addr) 'quote))
  674.          (let ((exec (address (cadr addr))))
  675.             (add-reference addr)
  676.             (setq retval (list* 7 4 (long-words exec)))))
  677.  
  678.         ((and (consp addr) (eq (car addr) 'symbol-function))
  679.          (let ((func (address (symbol-function (cadr addr)))))
  680.             (add-reference addr)
  681.             (setq retval (list* 7 4 (long-words func)))))
  682.  
  683.         ((symbolp addr)
  684.          (cond
  685.             ((member addr d-registers) 
  686.                 (setq retval (list 0 (symbol-value addr))))
  687.             ((member addr a-registers) 
  688.                 (setq retval (list 1 (symbol-value addr))))
  689.             (t 
  690.                 (add-reference `(symbol-value ,addr))
  691.                 (setq addr (symbol-value addr))
  692.                 (if (eq size 'long)
  693.                     (setq retval (list* 7 4 (long-words addr)))
  694.                     (setq retval (list 7 4 (mod addr #x10000)))))))
  695.  
  696.         ((consp addr)
  697.          (setq retval 
  698.             (cond
  699.                 ((member (car addr) a-registers) 
  700.                  (if (cdr addr)
  701.                      (list* 5 (symbol-value (car addr)) (cdr addr))
  702.                     (list 2 (symbol-value (car addr)))))
  703.                 ((member (car addr) a-inc-registers) 
  704.                  (list 3 (symbol-value (car addr))))
  705.                 ((member (car addr) a-dec-registers) 
  706.                  (list 4 (symbol-value (car addr))))
  707.                 ((and (symbolp (car addr)) (null (cdr addr)))
  708.                  (add-reference `(symbol-value ,(car addr)))
  709.                  (list* 7 1 (long-words (symbol-value (car addr)))))
  710.                 ((and (integerp (car addr)) (null (cdr addr)))
  711.                  (list* 7 1 (long-words (car addr))))
  712.                 (t (error "Unknown address expression: ~A" addr)))))
  713.  
  714.         ((integerp addr)
  715.          (if (eq size 'long)
  716.             (setq retval (list* 7 4 (long-words addr)))
  717.             (setq retval (list 7 4 (mod addr #x10000)))))
  718.             
  719.         (t (error "Unknown address expression: ~A" addr)))
  720.  
  721.     (if (> (length retval) 2)
  722.         (incf *assembler-local-address* (* 2 (length retval))))
  723.     (return retval))
  724.  
  725. ;;
  726. ;;    encoded-address-mode
  727. ;;    Returns the mode (integer) of the passed address structure.
  728. ;;
  729. (defun encoded-address-mode (addr)
  730.     (car addr))
  731.  
  732. (defun encoded-address-reg (addr)
  733.     (cadr addr))
  734.  
  735. (defun encoded-address-data (addr)
  736.     (cddr addr))
  737.     
  738. (defun assemble (assembler-instructions references &optional environment)
  739.   (let*
  740.     ((label-table (make-hash-table :test #'eql))
  741.       (newlist nil)
  742.       (codelist nil)
  743.       (*assembler-address* 0)
  744.       (*assembler-local-address* 0)
  745.       (*assembler-references* nil)
  746.       operator)
  747.  
  748.     (do ((n assembler-instructions (cdr n))
  749.          statement)
  750.         ((null n))
  751.         (setq statement (car n))
  752.         (cond
  753.             ;; if it is a label, add it to the hash table
  754.             ((symbolp statement) 
  755.              (setf (gethash statement label-table) *assembler-address*))
  756.             ((consp statement)
  757.              (if (integerp (car statement))     ;; skip address if there is one
  758.                  (setq statement (cdr statement)))
  759.              
  760.              ;; make sure there is a macro definition
  761.              (setq operator (car statement))
  762.              (unless (symbolp operator) 
  763.                  (error "Invalid instruction: ~A" operator))
  764.              (unless (macro-function operator)
  765.                  (error "No definition for instruction: ~A" statement))
  766.  
  767.              ;; expand the macro one time
  768.              (setq *assembler-local-address* 2)    ;; reset this each instruction
  769.              (setq statement (macroexpand-1 statement))
  770.              
  771.              ;; check for multiple statement result (assembler macro expansion)
  772.              (if (and (consp statement) (not (integerp (car statement))))
  773.                  ;; just splice in the new instructions and continue
  774.                 (setq n (append (list nil) statement (cdr n)))
  775.                 (if (consp statement)
  776.                     ;; This address is only correct because we are requiring
  777.                     ;; all branch destinations to be 16-bit offsets. 
  778.                     ;; This avoids having to calculate the sizes here.
  779.                     ;; i.e. each symbol becomes one 16-bit displacement word.
  780.                     (progn
  781.                         (incf *assembler-address* (* (length statement) 2))
  782.                         (push statement newlist)))))
  783.             
  784.             ;; error if not a symbol or a list
  785.             (t (error "Invalid label encountered: ~A" statement))))
  786.             
  787.     ;; Now go through and append all the sublists together,
  788.     ;; resolving branch addresses as we go.
  789.     ;; We only currently support 16-bit displacements in the branch
  790.     ;; instructions.
  791.  
  792.     (setq newlist (reverse newlist))
  793.     (setq *assembler-address* 0)
  794.     (dolist (statement newlist)
  795.         
  796.         ;; check for branch instructions
  797.         (setq operator (car statement))
  798.         (if (= (truncate operator #x1000) 6)
  799.             (if (and (consp (cdr statement))
  800.                     (symbolp (cadr statement)))
  801.                 (let* ((sym (cadr statement))
  802.                         (value (gethash sym label-table)))
  803.                     (unless value 
  804.                         (error "Label not found: ~A" sym))
  805.                     (unless (integerp value) 
  806.                         (error "Invalid label found.~%~ALabel: ~A Value: ~A" sym value))
  807.                     (setf (cadr statement) (- value (+ *assembler-address* 2))))))
  808.         
  809.         (incf *assembler-address* (* 2 (length statement)))
  810.         (dolist (n statement) (push n codelist)))
  811.         
  812.     (%build-function (reverse codelist) *assembler-references* environment)))
  813.  
  814. (defun add-reference (ref &optional (offset 0))
  815.     (push 
  816.         (cons ref (+ *assembler-address* *assembler-local-address* offset)) 
  817.         *assembler-references*))
  818.     
  819. ;;    add defasm to the common lisp package
  820.  
  821. (in-package :common-lisp)
  822. (export 'defasm)
  823.  
  824. (defmacro defasm (name lambda-list &rest forms)
  825.     (declare (unused lambda-list))    ;; this is just for documentation
  826.     (let ((doc-form nil))
  827.         (if (and (typep (car forms) 'string)
  828.                 (cdr forms))
  829.             (progn
  830.                 (setq doc-form 
  831.                     `((setf (documentation ',name 'function) ,(car forms))))
  832.                 (setq forms (cdr forms))))
  833.  
  834.         `(progn
  835.             ,@doc-form
  836.             (setf (symbol-function ',name) ,(car forms))
  837.             (null-environment (function ,name))
  838.             ',name))) 
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.